package com.glodon.paas.document.web.controller;

import static com.glodon.paas.document.web.controller.ActivityContants.APPID_DOCUMENT;
import static com.glodon.paas.document.web.controller.ActivityContants.ITEM_TYPE_FILE;
import static com.glodon.paas.document.web.controller.ActivityContants.activityType_delete;
import static com.glodon.paas.document.web.controller.ActivityContants.activityType_download;
import static com.glodon.paas.document.web.controller.ActivityContants.activityType_move;
import static com.glodon.paas.document.web.controller.ActivityContants.activityType_pkgDownload;
import static com.glodon.paas.document.web.controller.ActivityContants.activityType_publish;
import static com.glodon.paas.document.web.controller.ActivityContants.activityType_renameFile;
import static com.glodon.paas.document.web.controller.ActivityContants.activityType_restoreFile;
import static com.glodon.paas.document.web.controller.ActivityContants.activityType_share;
import static com.glodon.paas.document.web.controller.ActivityContants.activityType_unshare;
import static com.glodon.paas.document.web.controller.ActivityContants.activityType_upload;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.glodon.paas.account.api.bean.Communicate;
import com.glodon.paas.account.api.bean.User;
import com.glodon.paas.activity.api.bean.Activity;
import com.glodon.paas.activity.api.bean.ActivityIn;
import com.glodon.paas.activity.client.ActivityClient;
import com.glodon.paas.activity.client.ActivityClientHttpImpl;
import com.glodon.paas.document.api.bean.File;
import com.glodon.paas.document.biz.FileBiz;
import com.glodon.paas.document.dao.domain.FileInfoEntity;
import com.glodon.paas.document.dao.domain.ShareEntity;
import com.glodon.paas.document.service.ShareService;
import com.glodon.paas.document.service.util.WebService;
import com.glodon.paas.exception.PaasServerExceptionFactory;
import com.glodon.paas.util.ObjectUtil;
import com.glodon.paas.util.asyn.AsynWorker;

@Component("activityPublisher")
public class ActivityPublisher {
    private static Logger  logger         = LoggerFactory.getLogger(ActivityPublisher.class);
    
    @Autowired
    ActivityClient        activityClient;
    @Autowired
    private FileBiz       fileBiz;
    @Autowired
    private ShareService  shareService;
    @Autowired
    private AsynWorker    asynWorker;
    @Autowired
    private WebService    webService;

    private static boolean NOT        = false;
    
    //@Value("${api.internal.account.url}")
    private boolean       enable = true;

    public void setEnable(String value) {
        if("true".equals(value.trim().toLowerCase())){
            this.enable = true;
        }
    }
    public void setActivityClient(ActivityClient activityClient) {
        this.activityClient = activityClient;
    }

    /**
     * 向receiverIds中添加共享属性产生的活动接收者
     * 此时添加的是文件路径上左右共享者id
     * @param userId
     * @param itemId
     * @param receiverIds
     * @return
     */
    private Set<String> addReceiverForShare(String userId, String itemId, Set<String> receiverIds) {
        List<ShareEntity> shares = shareService.getSharesOnFile(userId, itemId, true);
        
        for(ShareEntity share : shares){
            receiverIds.add(share.getToUserId());
        }
        return receiverIds;
    }
    

    /**
     * 向receiverIds中添加公开属性产生的活动接收者
     * 如果文件路劲上有被公开，此时添加的是联系人列表用户id
     * @param userId
     * @param itemId
     * @param receiverIds
     * @return
     */
    private Set<String> addReceiverForPublish(String userId, String itemId, Set<String> receiverIds) {
        boolean isPublish = false; 
        
        FileInfoEntity file = fileBiz.getFile(itemId);
        if(file == null){
            return receiverIds;
        }
        
        // 当前文件
        if(file.isPublished()){
            isPublish = true;
        }
        
        // 祖先目录
        if(!isPublish){
            List<FileInfoEntity> files = fileBiz.getParents(file);
            for(FileInfoEntity f : files){
                if(f.isPublished()){
                    isPublish = true;
                    break;
                }
            }
        }

        if(isPublish){
            //获取联系人列表
            List<Communicate> list = webService.getContactList(userId);
            for(Communicate item : list){
                receiverIds.add(item.getContactId());
            }
        }
        
        return  receiverIds;
    }

    /**
     * 查询动态
     * 
     */
    public Activity[] query(Map<String, String> params) {
        return activityClient.query(params);
    }

    /**
     * 上传文件动态
     * @param actorId
     * @param actorName
     * @param itemId
     * @param itemName
     * @param asynchrony    是否异步执行
     */
    public void uploadFile(String actorId, String actorName, String itemId, String itemName, boolean asynchrony) {
        if(!enable){
            return;
        }
        if(asynchrony){
            try {
                asynWorker.submit(this, "uploadFile",
                                  new Object[]{actorId, actorName, itemId, itemName,NOT},
                                  null);
            } catch (Exception e) {
                logger.error(e.getMessage(),e);
            }
            return;
        }

        ActivityIn activity = new ActivityIn();
        activity.setActorId(actorId);
        activity.setActorName(actorName);
        activity.setItemId(itemId);
        activity.setItemType(ITEM_TYPE_FILE);
        activity.setItemName(itemName);
        activity.setActivityType(activityType_upload);

        activity.setReceiverIds(new HashSet<String>());
        addReceiverForShare(actorId, itemId, activity.getReceiverIds());
        addReceiverForPublish(actorId, itemId, activity.getReceiverIds());
        activity.addReceiver(itemId);
        activityClient.publish(activity);

    }

    // 下载文件
    public void downloadFile(String actorId, String actorName, String itemId, String itemName, boolean asynchrony) {
        if (!enable) {
            return;
        }

        if (asynchrony) {
            try {
                asynWorker.submit(this, "downloadFile", 
                                  new Object[] { actorId, actorName, itemId, itemName, NOT }, null);
            } catch (Exception e) {
                logger.error(e.getMessage(),e);
            }
            return;
        }

        ActivityIn activity = new ActivityIn();
        activity.setActorId(actorId);
        activity.setActorName(actorName);
        activity.setItemId(itemId);
        activity.setItemType(ITEM_TYPE_FILE);
        activity.setItemName(itemName);
        activity.setActivityType(activityType_download);

        activity.setReceiverIds(new HashSet<String>());
        addReceiverForShare(actorId, itemId, activity.getReceiverIds());
        addReceiverForPublish(actorId, itemId, activity.getReceiverIds());
        activity.addReceiver(itemId);
        activityClient.publish(activity);

    }

    public void publishFile(String actorId, String actorName, String itemId, String itemName, String token, boolean asynchrony) {
        if (!enable) {
            return;
        }

        if (asynchrony) {
            try {
                asynWorker.submit(this, "publishFile", 
                                  new Object[] { actorId, actorName, itemId, itemName,token, NOT },null);
            } catch (Exception e) {
                logger.error(e.getMessage(),e);
            }
            return;
        }
        
        ActivityIn activity = new ActivityIn();
        activity.setActorId(actorId);
        activity.setActorName(actorName);
        activity.setItemId(itemId);
        activity.setItemType(ITEM_TYPE_FILE);
        activity.setItemName(itemName);
        activity.setActivityType(activityType_publish);

        activity.setExt1(token);
        // activity.putExtension("token", token);

        activity.setReceiverIds(new HashSet<String>());
        addReceiverForShare(actorId, itemId, activity.getReceiverIds());
        addReceiverForPublish(actorId, itemId, activity.getReceiverIds());
        activity.addReceiver(itemId);
        activityClient.publish(activity);
    }

    // 共享文件
    public void shareFile(String actorId, String actorName, String itemId, String itemName, boolean asynchrony) {
        if (!enable) {
            return;
        }

        if (asynchrony) {
            try {
                asynWorker.submit(this, "shareFile",
                                  new Object[] { actorId, actorName, itemId, itemName, NOT },null);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
            return;
        }
        
        ActivityIn activity = new ActivityIn();
        activity.setActorId(actorId);
        activity.setActorName(actorName);
        activity.setItemId(itemId);
        activity.setItemType(ITEM_TYPE_FILE);
        activity.setItemName(itemName);
        activity.setActivityType(activityType_share);

        activity.setReceiverIds(new HashSet<String>());
        addReceiverForShare(actorId, itemId, activity.getReceiverIds());
        addReceiverForPublish(actorId, itemId, activity.getReceiverIds());
        activity.addReceiver(itemId);
        activityClient.publish(activity);
    }

    // 取消共享文件
    public void unShareFile(String actorId, String actorName, String itemId, String itemName, boolean asynchrony) {
        if (!enable) {
            return;
        }

        if (asynchrony) {
            try {
                asynWorker.submit(this, "unShareFile", 
                                  new Object[] { actorId, actorName, itemId, itemName, NOT }, null);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
            return;
        }
        
        ActivityIn activity = new ActivityIn();
        activity.setActorId(actorId);
        activity.setActorName(actorName);
        activity.setItemId(itemId);
        activity.setItemType(ITEM_TYPE_FILE);
        activity.setItemName(itemName);
        activity.setActivityType(activityType_unshare);
        
        activity.setReceiverIds(new HashSet<String>());
        addReceiverForShare(actorId, itemId, activity.getReceiverIds());
        addReceiverForPublish(actorId, itemId, activity.getReceiverIds());
        activity.addReceiver(itemId);
        activityClient.publish(activity);
    }
    
    public Integer getAppId() {
        return activityClient.getAppId();
    }

    //client test
    public static void main(String[] args) {
        // 初始化client
        ActivityClientHttpImpl activityClient = new ActivityClientHttpImpl();
        activityClient.setAppId(APPID_DOCUMENT);
        
        ActivityPublisher client = new ActivityPublisher();
        client.setActivityClient(activityClient);
        
        // 封装数据
        String[] itemId = new String[]{"fileId1","fileId2"};
        String[] itemName = new String[]{"你是人间四月天","三国演义"};
        
        // 发送数据
        client.downloadFiles("hc", "黄诚", itemId, itemName, false);
    }

    /**
     * 删除文件的一个版本
     * @param id
     * @param displayName
     * @param id2
     * @param name
     */
    public void delReversion(String actorId, String actorName, String itemId, String itemName, boolean asynchrony) {
       
    }

    /**
     * 批量下载文件
     * @param id
     * @param displayName
     * @param ids
     * @param fileName
     * @param b
     */
    public void downloadFiles(String actorId, String actorName, String[] fileIds, String[] fileNames, boolean asynchrony) {
        if(asynchrony){//异步
            try {
                asynWorker.submit(this, "downloadFiles", 
                                  new Object[]{actorId,actorName,fileIds,null,NOT},null);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
            return;
        }
        
        int size = fileIds.length;
        fileNames = new String[size];
        for(int i=0; i<size; i++){
            FileInfoEntity f = fileBiz.getFile(fileIds[i]);
            if(f != null){
                fileNames[i] = f.getName();
            }
        }
        
        ActivityIn activity = new ActivityIn();
        activity.setActorId(actorId);
        activity.setActorName(actorName);
        activity.setItemType(ITEM_TYPE_FILE);
        activity.setActivityType(activityType_pkgDownload);
        
        Map<String,Object> ext = new HashMap<String,Object>();
        ext.put("itemIds", fileIds);
        ext.put("itemNames", fileNames);
        ext.put("size", size);
        activity.setExt1(ObjectUtil.toJson(ext));

        activity.setReceiverIds(new HashSet<String>());
        addReceiverForShare(actorId, fileIds[0], activity.getReceiverIds());
        addReceiverForPublish(actorId, fileIds[0], activity.getReceiverIds());
        for(String id : fileIds){
            activity.addReceiver(id);
        }
        activityClient.publish(activity);
    }
    /**
     * @param id
     * @param displayName
     * @param id2
     * @param name
     * @param name2
     * @param b
     */
    public void rename(String actorId, String actorName, String itemId, String oldName, String newName, boolean asynchrony) {
        if (asynchrony) {
            try {
                asynWorker.submit(this, "rename", new Object[] { actorId, actorName, itemId, oldName, newName, NOT },
                                  null);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
            return;
        }
        
        ActivityIn activity = new ActivityIn();
        activity.setActorId(actorId);
        activity.setActorName(actorName);
        activity.setItemId(itemId);
        activity.setItemName(newName);
        activity.setItemType(ITEM_TYPE_FILE);
        activity.setActivityType(activityType_renameFile);
        activity.setExt1(oldName);

        activity.setReceiverIds(new HashSet<String>());
        addReceiverForShare(actorId, itemId, activity.getReceiverIds());
        addReceiverForPublish(actorId, itemId, activity.getReceiverIds());
        activity.addReceiver(itemId);
        activityClient.publish(activity);
    }

    /**
     * @param id
     * @param displayName
     * @param files
     * @param b
     */
    public void logicalDelFile(String actorId, String actorName, List<File> files, boolean asynchrony) {
        if(asynchrony){//异步
            try {
                asynWorker.submit(this, "logicalDelFile", 
                                  new Object[]{actorId, actorName,files,NOT},null);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
            return;
        }
        
        ActivityIn activity = new ActivityIn();
        activity.setActorId(actorId);
        activity.setActorName(actorName);
        activity.setItemType(ITEM_TYPE_FILE);
        activity.setActivityType(activityType_delete);
        
        int size = files.size();
        
        if(files.size() == 1){
            activity.setItemId(files.get(0).getId());
            activity.setItemName(files.get(0).getName());
        }else{
            Map<String,Object> ext = new HashMap<String,Object>();
            ext.put("size", size);
            
            String[] itemNams;
            if(size > 10){
                itemNams = new String[10];
            }else{
                itemNams = new String[size];
            }
            
            size = itemNams.length;
            for(int i=0; i<size;i++){
                itemNams[i] = files.get(i).getName();
            }
            ext.put("itemNames", itemNams);
            
            activity.setExt1(ObjectUtil.toJson(ext));
        }
        
        activity.setReceiverIds(new HashSet<String>());
        addReceiverForShare(actorId, files.get(0).getId(), activity.getReceiverIds());
        addReceiverForPublish(actorId, files.get(0).getId(), activity.getReceiverIds());
        for(File f :files){
            activity.addReceiver(f.getId());
        }
        activityClient.publish(activity);
    }
    /**
     * @param id
     * @param displayName
     * @param successItems
     * @param b
     */
    public void restoreFile(String actorId, String actorName, List<String> itemIds, boolean asynchrony) {
        if(asynchrony){//异步
            try {
                asynWorker.submit(this, "restoreFile", 
                                  new Object[]{actorId, actorName,itemIds,NOT},null);
            } catch (Exception e) { 
                logger.error(e.getMessage(), e);
            }
            return;
        }
        
        int size = itemIds.size();
        List<FileInfoEntity> fileList = new ArrayList<FileInfoEntity>(size);
        
        FileInfoEntity temp;
        for(String id : itemIds){
            temp = fileBiz.getFile(id);
            if(temp != null){
                fileList.add(temp);
            }
            //最多放10个文件
            if(fileList.size() >= 10){
                break;
            }
        }
        
        ActivityIn activity = new ActivityIn();
        activity.setActorId(actorId);
        activity.setActorName(actorName);
        activity.setItemType(ITEM_TYPE_FILE);
        activity.setActivityType(activityType_restoreFile);
        
        if(fileList.size() == 1){
            activity.setItemId(fileList.get(0).getId());
            activity.setItemName(fileList.get(0).getName());
        }else{
            Map<String,Object> ext = new HashMap<String,Object>();
            ext.put("size", size);
            
            size = fileList.size();
            String[] _itemIds = null;
            String[] _itemNams = null;
            if(size > 10){
                _itemIds = new String[10];
                _itemNams = new String[10];
            }else{
                _itemIds = new String[size];
                _itemNams = new String[size];
            }
            
            size = _itemIds.length;
            for(int i=0; i<size; i++){
                _itemIds[i] = fileList.get(i).getId();
                _itemNams[i] = fileList.get(i).getName();
            }
            ext.put("itemIds", _itemIds);
            ext.put("itemNames", _itemNams);
            
            activity.setExt1(ObjectUtil.toJson(ext));
        }
        
        activity.setReceiverIds(new HashSet<String>());
        addReceiverForShare(actorId, itemIds.get(0), activity.getReceiverIds());
        addReceiverForPublish(actorId, itemIds.get(0), activity.getReceiverIds());
        for(String id :itemIds){
            activity.addReceiver(id);
        }
        activityClient.publish(activity);
    }
    /**
     * @param id
     * @param displayName
     * @param successItems
     * @param parentId
     * @param b
     */
    public void moveFile(String actorId, String actorName, List<File> successItems, String parentId, boolean asynchrony) {
        if(asynchrony){//异步
            try {
                asynWorker.submit(this, "moveFile", 
                                  new Object[]{actorId, actorName,successItems,parentId,NOT},
                                  null);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
            return;
        }
        
        ActivityIn activity = new ActivityIn();
        activity.setActorId(actorId);
        activity.setActorName(actorName);
        activity.setItemType(ITEM_TYPE_FILE);
        activity.setActivityType(activityType_move);
        
        int size = successItems.size();

        if(size == 1){
            activity.setItemId(successItems.get(0).getId());
            activity.setItemName(successItems.get(0).getName());
        }else{
            Map<String,Object> ext = new HashMap<String,Object>();
            ext.put("size", size);
            
            String[] _itemIds = null;
            String[] _itemNams = null;
            if(size > 10){
                _itemIds = new String[10];
                _itemNams = new String[10];
            }else{
                _itemIds = new String[size];
                _itemNams = new String[size];
            }
            
            size = _itemIds.length;
            for(int i=0; i<size; i++){
                _itemIds[i] = successItems.get(i).getId();
                _itemNams[i] = successItems.get(i).getName();
            }
            ext.put("itemIds", _itemIds);
            ext.put("itemNames", _itemNams);
            
            activity.setExt1(ObjectUtil.toJson(ext));
        }

        FileInfoEntity parent = fileBiz.getFile(parentId);
        if(parent!=null){
            activity.setExt2(parent.getName());
        }
        
        activity.setReceiverIds(new HashSet<String>());
        addReceiverForShare(actorId, successItems.get(0).getId(), activity.getReceiverIds());
        addReceiverForPublish(actorId, successItems.get(0).getId(), activity.getReceiverIds());
        for(File f :successItems){
            activity.addReceiver(f.getId());
        }
        activityClient.publish(activity);
    }
 
    public void shareFile(String actorId, String actorName, String itemId, String itemName, List<User> toUsers,  boolean asynchrony) {
        if(asynchrony){//异步
            try {
                asynWorker.submit(this, "shareFile", 
                                  new Object[]{actorId, actorName,itemId,itemName,toUsers,NOT},
                                  null);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
            return;
        }
        int size = toUsers.size();
        if(size == 0){
            return;
        }
        
        ActivityIn activity = new ActivityIn();
        activity.setActorId(actorId);
        activity.setActorName(actorName);
        activity.setItemType(ITEM_TYPE_FILE);
        activity.setItemId(itemId);
        activity.setItemName(itemName);
        activity.setActivityType(activityType_share);
        
        //ext
        Map<String, Object> ext = new HashMap<String, Object>();
        ext.put("size", size);
        String[] _userIds = new String[size];
        String[] _userNames = new String[size];

        for (int i = 0; i < size; i++) {
            _userIds[i] = toUsers.get(i).getId();
            _userNames[i] = toUsers.get(i).getDisplayName();
        }
        ext.put("toUserIds", _userIds);
        ext.put("toUserNames", _userNames);
        activity.setExt1(ObjectUtil.toJson(ext));
 
        activity.setReceiverIds(new HashSet<String>());
        for(User u : toUsers){
            activity.addReceiver(u.getId());
        }
        activity.addReceiver(itemId);
        activityClient.publish(activity);
    }

    public void unShareFile(String actorId, String actorName, String itemId, String itemName, String toUserId, boolean asynchrony) {
        if(asynchrony){//异步
            try {
                asynWorker.submit(this, "unShareFile", 
                                  new Object[]{actorId, actorName,itemId,itemName,toUserId,NOT},
                                  null);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
            return;
        }

        ActivityIn activity = new ActivityIn();
        activity.setActorId(actorId);
        activity.setActorName(actorName);
        activity.setItemType(ITEM_TYPE_FILE);
        activity.setItemId(itemId);
        activity.setItemName(itemName);
        activity.setActivityType(activityType_unshare);
        
        User u = webService.getUser(toUserId);
        if(u == null){
            throw PaasServerExceptionFactory.notFoundException("user not found, userId="+toUserId, null);
        }
        
        activity.setExt1(u.getId());
        activity.setExt2(u.getDisplayName());
 
        activity.setReceiverIds(new HashSet<String>());
        activity.addReceiver(u.getId());
        activity.addReceiver(itemId);
        activityClient.publish(activity);
        
    }
//    public void unShareFiles(String actorId, String actorName, String itemId, String itemName, List<User> toUsers,  boolean asynchrony) {
//        if(asynchrony){//异步
//            try {
//                asynWorker.submit(this, "shareFiles", 
//                                  new Object[]{actorId, actorName,itemId,itemName,toUsers,NOT},
//                                  null);
//            } catch (Exception e) {
//                logger.error(e.getMessage(), e);
//            }
//            return;
//        }
//        int size = toUsers.size();
//        if(size == 0){
//            return;
//        }
//        
//        ActivityIn activity = new ActivityIn();
//        activity.setActorId(actorId);
//        activity.setActorName(actorName);
//        activity.setItemType(ITEM_TYPE_FILE);
//        activity.setItemId(itemId);
//        activity.setItemName(itemName);
//        activity.setActivityType(activityType_share);
//        
//        //ext
//        Map<String, Object> ext = new HashMap<String, Object>();
//        ext.put("size", size);
//        String[] _userIds = new String[size];
//        String[] _userNames = new String[size];
//
//        for (int i = 0; i < size; i++) {
//            _userIds[i] = toUsers.get(i).getId();
//            _userNames[i] = toUsers.get(i).getDisplayName();
//        }
//        ext.put("toUserIds", _userIds);
//        ext.put("toUserNames", _userNames);
//        activity.setExt1(ObjectUtil.toJson(ext));
// 
//        activity.setReceiverIds(new HashSet<String>());
//        for(User u : toUsers){
//            activity.addReceiver(u.getId());
//        }
//        activityClient.publish(activity);
//    }
}
